package jrain.fw.dao.mysql;

import java.util.List;
import java.util.Map;

import jrain.fw.core.cfg.CfgService;
import jrain.fw.core.consts.Consts;
import jrain.fw.core.dao.SqlParser;
import jrain.fw.core.dao.bean.SqlBean;
import jrain.fw.core.service.Service;
import jrain.fw.core.service.ServiceConst;
import jrain.fw.core.utils.FwUtils;
import jrain.fw.dao.common.parser.BaseSqlParser;
import jrain.fw.dao.common.utils.SqlUtils;
import jrain.utils.collection.CollectionUtils;
import jrain.utils.consts.BaseConst;
import jrain.utils.exception.ServiceException;
import jrain.utils.lang.StringUtils;

/**
 * <pre>
 * 作者：3244924214@qq.com
 * 描述：MySQL 语句解析
 * </pre>
 */
@Service(name = "mysql", group = ServiceConst.S_DAO_SQL_PARSER_SERVICE, module = ServiceConst.M_DAO)
public class MySqlSqlParser implements SqlParser {

	private final CfgService cfgService;
	private BaseSqlParser sqlParser = new BaseSqlParser();

	public MySqlSqlParser() {
		cfgService = FwUtils.getCfgService();
	}

	@SuppressWarnings("unchecked")
	protected Map<String, Object> getSqlInfo(String namespace, String statement, Map<String, Object> paramData) {
		String key = namespace + BaseConst.POINT + statement;
		Object value = cfgService.getCfgValue(Consts.CFG_TYPE_SQL, key);
		if (value == null) {
			String msg = "There is no corresponding SQL configuration item " + key;
			throw new ServiceException(msg);
		} else {
			return (Map<String, Object>) value;
		}
	}

	public SqlBean generateInsert(String namespace, String statement, Map<String, Object> paramData) {
		Map<String, Object> sqlInfo = getSqlInfo(namespace, statement, paramData);
		return generateInsert(sqlInfo, paramData);
	}

	public SqlBean generateInsert(Map<String, Object> sqlCfg, Map<String, Object> paramData) {
		SqlBean sqlObj = new SqlBean();
		String columnsStr = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_COLUMNS));
		String tableName = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_TABLE));
		List<Object> rsList = sqlObj.getParams();
		List<String> columns = CollectionUtils.valueOfList(columnsStr);
		StringBuilder sql = new StringBuilder();
		sql.append("insert into ");
		sql.append(tableName);
		sql.append(BaseConst.LEFT_XKH);
		columns.forEach(column -> {
			List<String> fields = CollectionUtils.valueOfList(column, " ");
			String columnCode = column;
			String fieldCode = SqlUtils.columnToField(columnCode);
			if (fields.size() == 2) {
				columnCode = fields.get(0);
				fieldCode = fields.get(1);
			}
			Object value = paramData.get(fieldCode);
			if (value != null) {
				sql.append(columnCode);
				sql.append(BaseConst.COMMA);
				rsList.add(value);
			}
		});
		sql.deleteCharAt(sql.lastIndexOf(BaseConst.COMMA));
		sql.append(")values(");
		sql.append(SqlUtils.createPrepared(rsList.size()));
		sql.append(BaseConst.RIGHT_XKH);
		sqlObj.setSql(sql);
		return sqlObj;
	}

	public SqlBean generateUpdate(String namespace, String statement, Map<String, Object> paramData) {
		Map<String, Object> sqlInfo = getSqlInfo(namespace, statement, paramData);
		return generateUpdate(sqlInfo, paramData);
	}

	public SqlBean generateUpdate(Map<String, Object> sqlCfg, Map<String, Object> paramData) {
		// SQL处理
		SqlBean sqlObj = sqlParser.parseSql(sqlCfg, paramData);
		return sqlObj;
	}

	public SqlBean generateDelete(String namespace, String statement, Map<String, Object> paramData) {
		Map<String, Object> sqlInfo = getSqlInfo(namespace, statement, paramData);
		return generateDelete(sqlInfo, paramData);
	}

	public SqlBean generateDelete(Map<String, Object> sqlCfg, Map<String, Object> paramData) {
		SqlBean sqlObj = sqlParser.parseSql(sqlCfg, paramData);
		return sqlObj;
	}

	public SqlBean generateQuery(String namespace, String statement, Map<String, Object> paramData) {
		Map<String, Object> sqlInfo = getSqlInfo(namespace, statement, paramData);
		return generateQuery(sqlInfo, paramData);
	}

	public SqlBean generateQuery(Map<String, Object> sqlCfg, Map<String, Object> paramData) {
		SqlBean sqlObj = sqlParser.parseSql(sqlCfg, paramData);
		return sqlObj;
	}

	public String generateCountSql(String sql) {
		int fromIndex = sql.indexOf(" from ");
		if (fromIndex == -1) {
			fromIndex = sql.indexOf(" FROM ");
		}
		if (fromIndex == -1) {
			throw new ServiceException("SQL parsing failed, failed to find from ");
		}
		String countAfter = sql.substring(fromIndex);
		sql = "SELECT COUNT(1) " + countAfter;
		return sql;
	}

	public String generatePageSql(String sql, long startRow, int pageSize) {
		String limit = " limit " + startRow + BaseConst.COMMA + pageSize;
		return sql + limit;
	}

}
